<?php
/*****************************************************************************
Copyright © 2008 The Regents of the University of Nevada
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/

interface iMap {
	function __construct();
	function delete();
	function save();
	function getArea();
	function hasBeenPopulated();
	function getCenterLat();
	function getCenterLong();
	function getCollection();
	function getCollectionID();
	function setCollectionID($int);
	function existsInCONTENTdm();
	function getHeight();
	function getID();
	function setID($int);
	function getLatN();
	function setLatN($float);
	function getLatS();
	function setLatS($float);
	function getLongE();
	function setLongE($float);
	function getLongW();
	function setLongW($float);
	function getPtr();
	function setPtr($int);
	function getRecordURL();
	function hasSiblingWithSameAliasPtrInDataStore();
	function hasSiblingWithSameIDInDataStore();
	function getSVGRect();
	function getThumbURL();
	function getWidth();
}

class Map implements iMap {

	private $collection_id, $id, $ptr, $lat_n, $lat_s, $long_e, $long_w;
	private $has_been_populated = false;
	private $collection;				// Collection object
	private $metadata = array();	// array of Field objects


	public function __construct($id = null, $populate = true) {
		if ($id) {
			$this->setID($id);
			if ($populate) {
				$this->populateSelf();
			}
		}
	}


	public final function delete() {
		return DataStore::getInstance()->deleteMap($this);
	}


	public final function save() {
		return DataStore::getInstance()->saveMap($this);
	}


	public static function getAll($page = 1, $results_per_page = 20,
	$sort = 'ptr', $sort_order = 'asc') {
		return DataStore::getInstance()->getAllMaps($page, $results_per_page,
			$sort, $sort_order);
	}


	public final function getArea() {
		return ($this->getLongE() - $this->getLongW())
			* ($this->getLatN() - $this->getLatS());
	}


	public final function hasBeenPopulated() {
		return $this->has_been_populated;
	}


	public final function getCenterLat() {
		return $this->getLatS() + ($this->getLatN() - $this->getLatS()) * 0.5;
	}


	public final function getCenterLong() {
		return $this->getLongW() + ($this->getLongE() - $this->getLongW()) * 0.5;
	}


	public final function getCollection() {
		if (!$this->collection instanceof Collection) {
			$this->collection = new Collection($this->collection_id);
		}
		return $this->collection;
	}


	public final function getCollectionID() {
		return $this->collection_id;
	}


	public final function setCollectionID($int) {
		$this->collection_id = $int;
	}


	public final function getHeight() {
		return $this->getLatN() - $this->getLatS();
	}


	public final function getID() {
		return $this->id;
	}


	public final function setID($int) { // access via constructor please
		$this->id = $int;
	}


	public final function existsInCONTENTdm() {
		$str = $this->getOAIRecord();
		$sxml = new SimpleXMLElement($str);
		$result = $sxml->GetRecord->record->header->identifier;
		if ((string) $result == $this->getOAIIdentifier()) {
			return true;
		}
		return false;
	}


	public final function getLatN() {
		return $this->lat_n;
	}


	public final function setLatN($float) {
		$this->lat_n = (float) $float;
	}


	public final function getLatS() {
		return $this->lat_s;
	}


	public final function setLatS($float) {
		$this->lat_s = (float) $float;
	}


	public final function getLongE() {
		return $this->long_e;
	}


	public final function setLongE($float) {
		$this->long_e = (float) $float;
	}


	public final function getLongW() {
		return $this->long_w;
	}


	public final function setLongW($float) {
		$this->long_w = (float) $float;
	}


	public function getMetadata($mapping=null) {
		if ($mapping && strpos($mapping, 'dc:') !== 0) return false;

		if (!$this->metadata[0] instanceof Field) {
			$str = $this->getOAIRecord();
			// sometimes loadXML will complain about whatever, so shut it up
			if (!$doc = @DOMDocument::loadXML(utf8_encode($str))) return false;
			$xp = new DOMXPath($doc);
			$xp->registerNamespace("dc", "http://purl.org/dc/elements/1.1/");
			foreach ($xp->query('//dc:*', $doc) as $node ) {
				$f = new Field((string) $node->nodeName);
				$f->setValue($node->nodeValue);
				$this->metadata[] = $f;
			}
		}
		if ($mapping) {
			foreach ($this->metadata as $f) {
				if ($f->getMapping() == $mapping) return $f;
			}
		}
		else return $this->metadata;
	}


	public static function getNumAll() {
		return DataStore::getInstance()->getNumMaps();
	}


	private function getOAIIdentifier() {
		return rtrim($this->getCollection()->getOAIIDPrefix(), ':') . ':'
			. trim($this->getCollection()->getAlias(), '/') . '/'
			. $this->getPtr();
	}


	private function getOAIRecord() {
		$url = $this->getOAIRecordURL();

		if (!$str = @file_get_contents($url)) {
			throw new UnknownHostException(sprintf(String::NO_OAI_RESPONSE, $url));
			return false;
		}
		return utf8_encode($str);
	}


	public function getOAIRecordURL() {
		$qa = array(
			'verb' => 'GetRecord',
			'metadataPrefix' => 'oai_dc',
			'identifier' => $this->getOAIIdentifier()
		);
		return trim($this->getCollection()->getBaseURL(), '/') . '/'
			. trim($this->getCollection()->getPathToOAI(), '/') . '?'
			. http_build_query($qa);
	}


	public final function getPtr() {
		return $this->ptr;
	}


	public final function setPtr($int) {
		$this->ptr = $int;
	}


	public final function hasSiblingWithSameIDInDataStore() {
		return DataStore::getInstance()->mapHasSiblingWithSameID($this);
	}


	public final function hasSiblingWithSameAliasPtrInDataStore() {
		return DataStore::getInstance()->mapHasSiblingWithSameCollectionAndPtr($this);
	}


	public final function getSVGRect() {
		return new SVGRect(
			$this->getLongW(),
			-$this->getLatN(),
			$this->getLongE() - $this->getLongW(),
			$this->getLatN() - $this->getLatS()
		);
	}


	public final function getWidth() {
		return $this->getLongE() - $this->getLongW();
	}


	public function getRecordURL() {
		return trim($this->getCollection()->getBaseURL(), '/')
			. '/u?' . $this->getCollection()->getAlias() . ',' . $this->getPtr();
	}


	private function populateSelf() {
		DataStore::getInstance()->loadMapProperties($this);
		$this->has_been_populated = true;
	}


	public function getThumbURL() {
		$qa = array(
			'CISOROOT' => $this->getCollection()->getAlias(),
			'CISOPTR' => $this->getPtr()
		);
		return $this->getCollection()->getBaseURL()
			. $this->getCollection()->getPathToThumbnail()
			. '?' . urldecode(http_build_query($qa));
	}

} // Map

?>
